﻿
//========================================全加密过滤器组件前端js代码开始===============================================
/**
 * 加密时使用的拼接字符，统一定义(可自行更改,如进行更改需要更改组件中后台中定义的统一拼字符)
 */
var splitCode=",";

// 加密算法加密方式(CBC/ECB)注意使用大写,不要加空格
var encrtypt_sm_method = "CBC";

/**
 *获取加密公钥
 */
// var publicKey;
function getGMPubKCode(){
	//国密2公钥
	return localStorage.getItem('key');
}

function setGMPubKCode(key){
	//国密2公钥
	publicKey = key;
}

/**
 * 是否启用全加密过滤器前段js设置(只有mx和vue生效)
 * @returns 返回true:启用 false: 不启用
 */
function isAllEncrypt(){
	return true;
}

/**
 * 全加密组件是否启用一次一密
 * @returns 返回true:启用 false: 不启用
 */
function isYCYM(){
	return false;
}

/**
 * 根据指定长度获取随机数
 * @param len 长度(如长度为3则返回6位的随机数)
 * @returns 返回指定位数的随机数
 */
function generateRandomCharacter(len) {
	var R = new SecureRandom();
	var A = new Array(len);
	R.nextBytes(A);
	var D = new SM3Digest().GetHex(A);
	return D.toString()
};

/**
 * 获取全加密组件加密所需的秘钥
 * @returns 返回秘钥
 */
function getWholeS4KCode(){
	//获取秘钥
	var wholeS4KCode=generateSM4Key();
	//当登陆时生成秘钥后放到sessionStorage以免刷新界面时丢失
	window.localStorage.setItem("whole_s4k_code", wholeS4KCode);
	if(encrtypt_sm_method == 'CBC'){
		//获取向量
		var wholeS4KIv=generateSM4Key();
		//当登陆时生成秘钥后放到sessionStorage以免刷新界面时丢失
		window.localStorage.setItem("whole_s4k_iv", wholeS4KIv);
	}
}
/**
 * 获取全加密组件加密所需的秘钥
 * @returns 返回秘钥
 */
function initWholeS4KCode(){
	var wholeS4KCode=window.localStorage.getItem("whole_s4k_code");
	if(""==wholeS4KCode || null == wholeS4KCode){
		//获取秘钥
		 wholeS4KCode=generateSM4Key();
		//生成秘钥后放到sessionStorage以免刷新界面时丢失
		window.localStorage.setItem("whole_s4k_code", wholeS4KCode);
	}
	//获取秘钥
	return wholeS4KCode;
}
/**
 * 获取全加密组件加密所需的向量
 * @returns 返回秘钥
 */
function initWholeS4KIv(){
	var wholeS4KIv = window.sessionStorage.getItem("whole_s4k_iv");
	if("" == wholeS4KIv || null == wholeS4KIv){
		//获取秘钥
		wholeS4KIv = generateSM4Key();
		//生成秘钥后放到sessionStorage以免刷新界面时丢失
		window.sessionStorage.setItem("whole_s4k_iv", wholeS4KIv);
	}
	//获取秘钥
	return wholeS4KIv;
}
/**
 * 判断是否已某个请求结尾
 * @returns 返回true : 是 false:否
 */
function endUrl(str,target) {
    return str.substring(str.length-target.length)  === target;
}

// 获取固定秘钥
function getFixedCode(){
	return `${firstKcode}${secondKcode}${thirdKcode}`;
//	return getCode();
}

//获取固定向量
function getFixedIv(){
	return `${firstIv}${secondIv}${thirdIv}`;
//	return getCode();
}

//==================================================VUE框架加解密函数 开始========================================
/**
 * 加密请求数据
 * @param plainText 需要加密的数据
 * @returns  返回加密后的数据
 */
export function dataEncrypt(params){
	//判断是否使用全加密组件,true:启用  false:不启用
	if(!isAllEncrypt()){
		return params;
	}
	var KCode=null;
	var iv = null;
	if(isYCYM()){
		// KCode=window.localStorage.getItem("key");
		KCode=initWholeS4KCode(); //发起向后端的第一个请求前需要调用生成秘钥的方法
		iv=initWholeS4KIv();
		// KCode=window.sessionStorage.getItem("whole_s4k_code");
		// iv=window.sessionStorage.getItem("whole_s4k_iv");
	}else{
		KCode=getFixedCode();
		iv = getFixedIv();
	}
	if("" == KCode || null == KCode){
		return;
	}
	//摘要加密和sm4加密  说明 splitCode:统一定义的拼接字符；
	var plainEncrypt = null;
	if (encrtypt_sm_method != 'CBC') {
		plainEncrypt = SG_sm4encrypt(SG_sm3encrypt(params)+params,KCode);
		//sm2加密  说明 splitCode:统一定义的拼接字符；
		plainEncrypt = SG_sm2Encrypt(KCode, getGMPubKCode())+splitCode + plainEncrypt;
		return plainEncrypt;
	}
	if("" == iv || null == iv){
		return;
	}
	var sm4=new SM4();
	plainEncrypt = sm4.encrypt_cbc(SG_sm3encrypt(params)+params,KCode, iv);
	//sm2加密  说明 splitCode:统一定义的拼接字符；
	plainEncrypt = SG_sm2Encrypt(KCode, getGMPubKCode())+splitCode + plainEncrypt + splitCode + SG_sm2Encrypt(iv, getGMPubKCode());
	return plainEncrypt;
}

/**
 * 解密数据
 * @param plainText 需要解密的数据
 * @returns 返回解密后的数据
 */
export function dataDecrypt(params){
	//判断是否使用全加密组件,true:启用  false:不启用
	if(!isAllEncrypt()){
		return params;
	}
	//从参数对象中获取key 为cipherText，如参数为空或不包含则直接返回当前参数
	if(null != params && "undefined" != typeof(params.cipherText)){  
		params=params.cipherText;
	}else{
		return params;
	}
	var KCode=null;
	var iv=null;
	if(isYCYM()){
//		KCode=window.localStorage.getItem("KCode");
		KCode=initWholeS4KCode();
		iv=initWholeS4KIv();
		// KCode=window.sessionStorage.getItem("whole_s4k_code");
		// iv=window.sessionStorage.getItem("whole_s4k_iv");
	}else{
		KCode=getFixedCode();
		iv = getFixedIv();
	}
	if("" == KCode || null == KCode){
		return;
	}
	try {
		//解密数据，
		var decryptData	 = null;
		if (encrtypt_sm_method != 'CBC') {
			decryptData	 = SG_sm4decrypt(params, KCode);
		} else {
			// debugger
			if("" == iv || null == iv){
				return;
			}
			var sm4=new SM4();
			decryptData	 = sm4.decrypt_cbc(params, KCode, iv);
		}
		var digest = decryptData.substring(0,64);
		var plainEncrypt =decryptData.substring(64,decryptData.length);
		// debugger
		//对比判断传输是否遭到破坏
		if(digest != SG_sm3encrypt(plainEncrypt)){
			return;
		}
	} catch(err) {
		Vue.prototype.$message({
            message: "网络出错,请刷新重试",
            type: "warning",
          });
		return;
	}
	return plainEncrypt;
}

//==================================================VUE框架加解密函数 开始========================================

//==================================================MX框架加解密函数 开始========================================
/**
 * 对请求参数体加密
 * @param params 需要加密的请求参数体
 * @returns 返回密文
 */
function wholeEncrypt(params){
	//判断是否使用全加密组件,true:启用  false:不启用
	if(!isAllEncrypt()){
		return params;
	}
	//判断是否使用一次一密对请求后的所有参数加密  true:启用 fasle:不启用
	if(isYCYM()){
		//使用一次一密加密请求参数体
		return sessionS4KCodeEncryptData(params);
	}
	//使用固定秘钥加密请求参数体
	return fixedS4KCodeEncryptData(params);
}
/**
 * 对请求参数体解密
 * @param params 需要解密的请求参数体
 * @returns 返回明文
 */
function wholeDecrypt(params){
	//判断是否使用全加密组件,true:启用  false:不启用
	if(!isAllEncrypt()){
		return params;
	}
	//判断是否使用一次一密对请求后的所有参数解密 true:启用 fasle:不启用
	if(isYCYM()){
		//使用一次一密解密请求参数体
		return sessionS4KCodeDecryptData(params);
	}
	//使用固定秘钥解密请求参数体
	return fixedS4KCodeDecryptData(params);
}

//==================================================MX框架加解密函数 结束========================================

//====================================MX框架全加密组件使用一次一密加密请求后的所有参数开始=========================================

/**
 * 全加密过滤器组件一次一密加密
 * @returns 返回密文串
 */
function sessionS4KCodeEncryptData(params){
	//获取会话秘钥
	var wholeS4KCode =window.localStorage.getItem("whole_s4k_code");
	if("" == wholeS4KCode || null == wholeS4KCode){
		return;
	}
	//获取随机数
	var requstNum = generateRandomCharacter(3);
	// 加密
	if (encrtypt_sm_method != 'CBC') {
		//摘要加密和sm4加密  说明 splitCode:统一定义的拼接字符；
		var plainText=SG_sm4encrypt(SG_sm3encrypt(requstNum+params)+requstNum+params,wholeS4KCode);
		//sm2加密  说明 splitCode:统一定义的拼接字符；
		return SG_sm2Encrypt(wholeS4KCode, getGMPubKCode())+splitCode + plainText;
	}

	var iv =window.localStorage.getItem("whole_s4k_iv");
	if("" == iv || null == iv){
		return;
	}
	//摘要加密和sm4加密  说明 splitCode:统一定义的拼接字符；
	var sm4=new SM4();
	var plainText=sm4.encrypt_cbc(SG_sm3encrypt(requstNum+params)+requstNum+params,wholeS4KCode, iv);
	//sm2加密  说明 splitCode:统一定义的拼接字符；
	return SG_sm2Encrypt(wholeS4KCode, getGMPubKCode())+splitCode + plainText + splitCode + SG_sm2Encrypt(iv, getGMPubKCode());
}
/**
 * 全加密过滤器组件一次一密解密
 * @returns 返回密文串
 */
function sessionS4KCodeDecryptData(params){
	//从参数对象中获取key 为cipherText，如参数为空或不包含则直接返回当前参数
	if(null != params && "undefined" != typeof(params.cipherText)){  
		params=params.cipherText;
	}else{
		return params;
	}
	//获取会话秘钥，如果无法从localStorage中获取，则证明localStorage中的值被销毁或篡改，提示程序出错；
	var wholeS4KCode =window.localStorage.getItem("whole_s4k_code");
	if("" == wholeS4KCode || null == wholeS4KCode){
		return;
	}
	try {
		//解密数据，获取到摘要加明文
		var decryptData	 = null;
		if (encrtypt_sm_method != 'CBC') {
			decryptData	= SG_sm4decrypt(params, wholeS4KCode);
			
		} else {
			var iv = window.localStorage.getItem("whole_s4k_iv")
			if("" == iv || null == iv){
				return;
			}
			var sm4=new SM4();
			decryptData = sm4.encrypt_cbc(params, wholeS4KCode, iv);
		}
		//截取摘要
		var digest = decryptData.substring(0,64);
		//截取明文
		var plainText =decryptData.substring(64,decryptData.length);
		//对比判断传输是否遭到破坏
		if(digest != SG_sm3encrypt(plainText)){
			return;
		}
		plainText = decryptData.substring(72,decryptData.length);
	} catch(err) {
		Vue.prototype.$message({
            message: "网络出错,请刷新重试",
            type: "warning",
          });
		return;
	}
	//当返回明文包含html标签是转换成json对象
	if(plainText.indexOf("<html>") == -1){
		plainText = JSON.parse(plainText);
	}
	return plainText;
}
//====================================MX框架全加密组件使用一次一密加密请求后的所有参数开始 =========================================
//====================================MX框架全加密组件固定秘钥加密请求后的所有参数开始=======================================

//请求信息加密 fixedS4KCodeEncryptData
function fixedS4KCodeEncryptData(params) {
	//获取随机数
	var requstNum = generateRandomCharacter(3);
	//生成摘要拼接随机数和明文
	var cipherText = SG_sm3encrypt(requstNum+params)+requstNum+params;
	//加密参数
	if (encrtypt_sm_method != 'CBC') {
		cipherText = SG_sm4encrypt(cipherText, getFixedCode());
	} else {
		var sm4=new SM4();
		cipherText = sm4.encrypt_cbc(cipherText, getFixedCode(), getFixedIv());
	}
	return cipherText;
}
//对返回信息进行解密  fixedS4KCodeDecryptData 
function fixedS4KCodeDecryptData(params) {
	//从参数对象中获取key 为cipherText，如参数为空或不包含则直接返回当前参数
	if(null != params && "undefined" != typeof(params.cipherText)){  
		params=params.cipherText;
	}else{
		return params;
	}
	
	try {
		 //解密获取摘要加明文
		var decryptData	 = null;
		if (encrtypt_sm_method != 'CBC') {
			decryptData	 = SG_sm4decrypt(params, getFixedCode());
		} else {
			var sm4=new SM4();
			decryptData	 = sm4.encrypt_cbc(params, getFixedCode(), getFixedIv());
		}
		//通过截取获取摘要
		var digest = decryptData.substring(0,64);
		//通过截取获取随机数加民本
		var randValue =decryptData.substring(64,decryptData.length);
		//判断
		if(digest !=SG_sm3encrypt(randValue)){
			return;
		}else{
			params = decryptData.substring(72,decryptData.length);
		}
	} catch(err) {
		Vue.prototype.$message({
            message: "网络出错,请刷新重试",
            type: "warning",
          });
		return;
	}
	if(params.indexOf("<html>") == -1){
		params = JSON.parse(params);
	}
	return params;
}
//=====================================MX框架全加密组件固定秘钥加密请求后的所有参数结束========================================
//========================================全加密过滤器组件前端js代码结束===============================================